<template>
  <a-modal :width="1000" :title="title" @cancel="close" :visible="visible" unmount-on-close>
    <div class="position-map">
      <!-- 搜索框 -->
      <div class="search" v-if="!readonly">
        <a-select
          :model-value="selectVal"
          v-model:input-value="keyword"
          placeholder="请输入关键字选取地点"
          :default-active-first-option="false"
          :filter-option="false"
          allow-search
          :popup-visible="selectFocus && (tips.length > 0 || keyword != '')"
          @focus="handleFocus"
          @blur="handleBlur"
          @search="handleSearch"
          @change="handleChange"
        >
          <!-- 不显示 下拉按钮 -->
          <template #arrow-icon></template>
          <a-option v-if="keyword" value="keyword" label="keyword">
            <icon-search class="icon" />
            {{ keyword }}
          </a-option>
          <a-option v-for="(d, i) in tips" :value="i" :key="i">
            <icon-location class="icon" />
            {{ d.title }}
          </a-option>
        </a-select>

        <div v-show="placeSearchShow" id="panel" style="width: 300px; height: 300px"></div>
      </div>

      <!-- 地图容器 -->
      <div id="mapContainer" class="map"></div>
    </div>
    <template #footer>
      <a-button @click="close">关闭</a-button>
      <a-button type="primary" @click="handleOk" v-if="!readonly">确认</a-button>
    </template>
  </a-modal>
</template>

<script>
  import { loadMapScript } from '@/utils/loadMap'

  export default {
    name: 'LnglatPickerModal',
    props: {
      readonly: {
        type: Boolean,
        default: false,
      },
      title: {
        type: String,
        default: '门店坐标',
      },
    },
    emits: ['change'],
    data() {
      return {
        mapService: 'AMap',
        map: null,
        disableMixinInit: false, // 禁止mixin初始化操作
        disableMixinMounted: true,
        keyword: '',
        selectVal: undefined,
        placeSearchShow: false,
        tips: [],
        visible: false,
        pickedLnglat: undefined,
        selectFocus: false,
      }
    },
    methods: {
      handleFocus() {
        this.selectFocus = true
        this.placeSearchShow = false
      },
      handleBlur() {
        this.selectFocus = false
      },
      open(lnglat) {
        this.point = lnglat
        this.visible = true
        // 加载地图
        return new Promise((resolve) => {
          loadMapScript().then(() => {
            this.$nextTick(() => {
              this.init()
              resolve(this.map)
            })
          })
        })
      },
      close() {
        this.map = null
        this.visible = false
      },
      init() {
        this.initMap()
        if (!this.readonly) {
          this.initMarkerEditor()
        }
        this.initPickerPoint()
      },
      setCity(map, pointCityName) {
        map && map.setCity(pointCityName)
      },
      // 标注编辑器
      initMarkerEditor() {
        this.polyfillOnClick((point) => {
          this.handleNewMarker(point)
        })
        // 分发
        if (this.mapService == 'AMap') {
          this.initPlaceSearchAMap()
        } else {
          this.initPlaceSearchBMap()
        }
      },
      // 初始化标注点
      initPickerPoint() {
        console.log('🐳 > initPickerPoint > this.point', this.point)
        if (!this.point) return
        const lnglat = this.point.split(',')
        this.polyfillAddMarker(lnglat, '门店坐标')
        this.polyfillSitFitView()
      },
      // AMap begin
      initPlaceSearchAMap() {
        //输入提示
        this.autocomplete = new AMap.AutoComplete({
          city: '全国',
        })
        // POI搜所
        this.placeSearch = new AMap.PlaceSearch({
          pageSize: 5, // 单页显示结果条数
          pageIndex: 1, // 页码
          panel: 'panel',
          // citylimit: true,
          autoFitView: false,
          map: this.map,
        })
        // POI选中
        this.placeSearch.on('selectChanged', (e) => {
          const { location } = e.selected.data
          const lnglat = [location.KL, location.kT]
          this.handleNewMarker(lnglat)
          this.polyfillSitFitView()
        })
      },
      // AMap end
      // BMap begin
      initPlaceSearchBMap() {
        const localSearch = new BMap.LocalSearch(this.map, {
          //智能搜索
          onSearchComplete: async () => {
            //获取第一个智能搜索的结果
            const point = localSearch.getResults().getPoi(0).point
            const tpoint = await this.translateLnglatBMap([point.lng, point.lat])
            this.handleNewMarker(tpoint)
            this.polyfillSitFitView()
          },
        })
        this.autocomplete = new BMap.Autocomplete({
          //建立一个自动完成的对象
          input: document.getElementById('suggestInput'),
          location: this.map,
        })
        this.autocomplete.addEventListener('onconfirm', (e) => {
          const _value = e.item.value
          const myValue = _value.province + _value.city + _value.district + _value.street + _value.business
          localSearch.search(myValue)
        })
      },
      // BMap end
      handleNewMarker(lnglat) {
        const sinput = document.getElementById('suggestInput')
        if (sinput) {
          sinput.blur()
        }
        this.selectVal = undefined
        this.placeSearchShow = false
        this.polyfillClearMap()
        this.polyfillAddMarker(lnglat, '门店坐标')
        this.pickedLnglat = lnglat
      },
      handleSearch(keyword) {
        if (!keyword) {
          this.tips = []
          return
        }
        // 搜索关键字
        this.polyfillAutocompleteOnsearch(keyword, (res) => {
          this.tips = res
        })
      },
      handleChange(v) {
        if (v == 'keyword') {
          // PIO搜索
          this.placeSearch.search(this.keyword, () => {
            this.placeSearchShow = true
            this.map.clearMap()

            // 清空selected值
            this.selectVal = ''
            this.selectFocus = false
          })
          return
        }
        const lnglat = this.tips[v].lnglat
        this.handleNewMarker(lnglat)
        this.polyfillSitFitView()
        // 清空selected值
        this.selectVal = ''
        this.selectFocus = false
      },

      handleOk() {
        this.close()
        if (this.pickedLnglat) {
          if (this.mapService == 'BMap') {
            this.$emit('change', this.pickedLnglat)
            return
          }
          // 逆编码识别
          this.polyfillGeocoderGetLocation(this.pickedLnglat, (address, res) => {
            this.$emit('change', this.pickedLnglat, res)
          })
        }
      },
      addMapControl() {},
      initMapCallback() {},
      polyfillNewMap(config = {}, containerId = 'mapContainer') {
        console.log('MapLoad--load newMap')
        const { center = [116.397428, 39.90923], zoom = 16 } = config
        if (this.mapService == 'AMap') {
          this.map = new AMap.Map(containerId, {
            center,
            zoom,
            ...config,
          })
        } else {
          this.map = new BMap.Map(containerId, {
            coordsType: 3, // 转为高德使用的火星坐标系
          })
          var point = new BMap.Point(...center)
          this.map.centerAndZoom(point, zoom)
          if (config.zoomEnable == false) {
            this.map.disableScrollWheelZoom()
            this.map.disableDoubleClickZoom()
          } else {
            this.map.enableScrollWheelZoom()
          }
          if (config.dragEnable == false) {
            this.map.disableDragging()
          }
        }
      },
      // 返回标注的坐标
      polyfillMarkerPosition(marker) {
        if (this.mapService == 'AMap') {
          const { KL, kT } = marker.getPosition()
          return [KL, kT]
        }
        const { lng, lat } = marker.getPosition()
        return [lng, lat]
      },
      // 增加工具条
      polyfillAddToolBar(offset = [10, 10]) {
        if (this.mapService == 'AMap') {
          this.map.addControl(
            new AMap.ToolBar({
              position: 'RB',
              offset,
            })
          )
        } else {
          this.map.addControl(
            new BMap.NavigationControl({
              type: BMAP_NAVIGATION_CONTROL_ZOOM,
              anchor: BMAP_ANCHOR_BOTTOM_RIGHT,
              offset: new BMap.Size(...offset),
            })
          )
        }
      },
      // 清空点聚合覆盖物
      polyfillClearCluster() {
        if (!this.markerCluster) return
        if (this.mapService == 'AMap') {
          this.markerCluster.setData([])
        } else {
          this.markerCluster.clearMarkers()
        }
      },
      // 清空覆盖物
      polyfillClearMap() {
        if (!this.map) return
        if (this.mapService == 'AMap') {
          this.map.clearMap()
        } else {
          this.map.clearOverlays()
        }
      },
      // 缩放地图到合适的视野级别
      polyfillSitFitView() {
        if (this.mapService == 'AMap') {
          this.map.setFitView(null, true)
        } else {
          let points = []
          this.map.getOverlays().map((item) => {
            if ('point' in item) {
              if (item.point) points.push(item.point)
            } else {
              const pathA = item.getPath()
              points = [...points, ...pathA]
            }
          })
          this.map.setViewport(points)
        }
      },
      // 建立带箭头的折线
      polyfillAddPolyline(path, config) {
        if (this.mapService == 'AMap') {
          const passedPolyline = new AMap.Polyline({
            map: this.map,
            strokeColor: '#3D80FF', //线颜色
            strokeWeight: 8, //线宽
            strokeOpacity: 1, //线透明度
            showDir: true,
            ...config,
          })
          return passedPolyline
        } else {
          const pointPath = path.map((lnglat) => {
            return new BMap.Point(...lnglat)
          })
          // var sy = new BMap.Symbol(BMap_Symbol_SHAPE_BACKWARD_OPEN_ARROW, {
          //   scale: 0.6, //图标缩放大小
          //   strokeColor: "#fff", //设置矢量图标的线填充颜色
          //   strokeWeight: "2" //设置线宽
          // });
          // const icons = new BMap.IconSequence(sy, '10', '30');
          const polyline = new BMap.Polyline(pointPath, {
            enableEditing: false, //是否启用线编辑，默认为false
            enableClicking: false, //是否响应点击事件，默认为true
            // icons:[icons],
            strokeWeight: '8', //折线的宽度，以像素为单位
            strokeOpacity: 1, //折线的透明度，取值范围0 - 1
            strokeColor: '#3D80FF', //折线颜色
            ...config,
          })
          this.map.addOverlay(polyline) //增加折线
          return polyline
        }
      },
      // 建立多边形覆盖物
      polyfillAddPolygon(path) {
        if (this.mapService == 'AMap') {
          const polygon = new AMap.Polygon({
            path,
            strokeWeight: 2,
            strokeColor: '#2C72FF',
            fillColor: '#6A9CFF',
            fillOpacity: 0.3,
            zIndex: 50,
            bubble: false,
          })
          return polygon
        } else {
          const pointPath = path.map((lnglat) => {
            return new BMap.Point(...lnglat)
          })
          const polygon = new BMap.Polygon(pointPath, {
            strokeWeight: 2,
            strokeColor: '#2C72FF',
            fillColor: '#6A9CFF',
            fillOpacity: 0.3,
            strokeOpacity: 1,
            enableClicking: true,
          })
          this.map.addOverlay(polygon)
          return polygon
        }
      },
      // 监听click
      polyfillOnClick(callback) {
        if (this.mapService == 'AMap') {
          this.map.on('click', (ev) => {
            const { lnglat } = ev
            callback([lnglat.KL, lnglat.kT])
          })
        } else {
          this.map.addEventListener('click', (ev) => {
            const { point } = ev
            callback([point.lng, point.lat])
          })
        }
      },
      // 地点自动提示
      polyfillAutocompleteOnsearch(keyword, callback) {
        if (this.mapService == 'AMap') {
          this.autocomplete.search(keyword, (status, res) => {
            if (status == 'complete') {
              const result = res.tips
                .filter((item) => item.location)
                .map((item) => {
                  return {
                    title: item.name,
                    lnglat: [item.location.KL, item.location.kT],
                    district: item.district,
                    address: item.address instanceof Array ? '' : item.address,
                  }
                })
              callback(result)
            }
          })
        }
      },
      // 增加标注点
      polyfillAddMarker(lnglat, title, config) {
        let marker
        if (this.mapService == 'AMap') {
          // 创建标注
          marker = new AMap.Marker({
            position: lnglat,
            title,
            ...config,
          })
          // 将标注添加到地图中
          this.map.add(marker)
        } else {
          const point = new BMap.Point(...lnglat)
          // 创建标注
          marker = new BMap.Marker(point, {
            title,
            ...config,
          })
          // 将标注添加到地图中
          this.map.addOverlay(marker)
        }
        return marker
      },
      // 增加一个icon标注
      polyfillAddIconMarker({ lnglat, angle = 0, addOverlay = true, enableMassClear = true }, iconConfig) {
        if (this.mapService == 'AMap') {
          // 创建一个 icon
          const myIcon = new AMap.Icon({
            image: iconConfig.image,
            size: new AMap.Size(...iconConfig.size),
            imageSize: new AMap.Size(...iconConfig.imageSize),
          })
          // 将 icon 传入 marker
          const myMarker = new AMap.Marker({
            position: lnglat,
            icon: myIcon,
            angle,
          })
          // 将 markers 添加到地图
          this.map.add(myMarker)
          return myMarker
        } else {
          var myIcon = new BMap.Icon(iconConfig.image, new BMap.Size(...iconConfig.size), {
            imageSize: new BMap.Size(...iconConfig.imageSize),
          })
          // 创建Marker标注，使用小车图标
          const point = new BMap.Point(...lnglat)
          const myMarker = new BMap.Marker(point, {
            icon: myIcon,
            rotation: angle,
            enableMassClear,
          })
          // 将标注添加到地图
          if (addOverlay) {
            this.map.addOverlay(myMarker)
          }
          return myMarker
        }
      },
      // 自定义标注
      polyfillAddCustomMarker(lnglat, markerContent, offset = [0, 0]) {
        if (this.mapService == 'AMap') {
          const customMarker = new AMap.Marker({
            position: lnglat,
            // 将 html 传给 content
            content: markerContent,
            // 以 icon 的 [center bottom] 为原点
            offset: new AMap.Pixel(...offset),
          })
          this.map.add(customMarker)
          return customMarker
        } else {
          const infoWindow = new BMap.InfoWindow(markerContent, {
            title: '',
            enableCloseOnClick: false,
            enableMessage: false,
            offset: new BMap.Size(0, -12),
          })
          this.map.openInfoWindow(infoWindow, new BMap.Point(...lnglat))
        }
      },
      // 逆地址解析
      polyfillGeocoderGetLocation(lnglat, callback) {
        if (this.mapService == 'AMap') {
          const geocoder = new AMap.Geocoder({
            // city: "010", //城市设为北京，默认：“全国”
            // radius: 1000 //范围，默认：500
          })
          const point = new AMap.LngLat(...lnglat)
          geocoder.getAddress(point, (status, result) => {
            let address
            if (status === 'complete' && result.regeocode) {
              address = result.regeocode.formattedAddress
            } else {
              console.log('根据经纬度查询地址失败')
            }
            callback(address, result.regeocode)
          })
        } else {
          const geocoder = new BMap.Geocoder({ extensions_town: true })
          // 根据坐标得到地址描述
          const point = new BMap.Point(...lnglat)
          geocoder.getLocation(point, function (result) {
            let address
            if (result) {
              address = result.address
            }
            callback(address)
          })
        }
      },
      // 地区搜索
      polyfillDistrictSearch(place, callback) {
        if (this.mapService == 'AMap') {
          const opts = {
            subdistrict: 1, //返回下一级行政区
            showbiz: false, //最后一级返回街道信息
            extensions: 'all',
          }
          const districtSearch = new AMap.DistrictSearch(opts) //注意：需要使用插件同步下发功能才能这样直接使用
          districtSearch.search(this.form.pointCityCode, (status, result) => {
            if (status == 'complete') {
              const bounds = result.districtList[0].boundaries
              callback(bounds)
            }
          })
        } else {
          const bdary = new BMap.Boundary()
          bdary.get(place, (rs) => {
            //获取行政区域
            this.map.clearOverlays() //清除地图覆盖物
            var count = rs.boundaries.length //行政区域的点有多少个
            if (count === 0) {
              alert('未能获取当前输入行政区域')
              return
            }
            const boundaries = res.boundaries.map((boundary) =>
              boundary.split(';').map((point) => (([lng, lat]) => ({ lng, lat }))(point.split(',').map((p) => +p)))
            )
            callback(boundaries)
          })
        }
      },
      // 设置视野级别和中心点
      polyfillSetZoomAndCenter(zoom, center) {
        if (this.mapService == 'AMap') {
          this.map.setZoomAndCenter(zoom, center)
        } else {
          this.map.setZoom(zoom)
          if (Array.isArray(center)) {
            const point = new BMap.Point(...center)
            this.map.setCenter(point)
            return
          }
          this.map.setCenter(center)
        }
      },
      // 百度地图坐标转换
      translateLnglatBMap(lnglat) {
        if (!this.convertorBMap) {
          this.convertorBMap = new BMap.Convertor()
        }
        return new Promise((resolve) => {
          const point = new BMap.Point(...lnglat)
          this.convertorBMap.translate([point], 5, 3, (res) => {
            const point = res.points[0]
            resolve([point.lng, point.lat])
          })
        })
      },
      // 百度地图坐标转换 多个
      translateManyLnglatBMap(self, key, callback) {
        if (!this.convertorBMap) {
          this.convertorBMap = new BMap.Convertor()
        }
        const points = self.map((item) => {
          return new BMap.Point(...(key ? item[key] : item))
        })
        this.convertorBMap.translate(points, 5, 3, (res) => {
          const transPoints = res.points
          for (let index = 0; index < transPoints.length; index++) {
            const transLnglat = Object.values(transPoints[index])
            if (key) {
              self[index][key] = transLnglat
            } else {
              self[index] = transLnglat
            }
          }
          callback(self)
        })
      },
      // 转百度坐标点
      toBMapPoint(x, y) {
        var x_pi = (3.14159265358979324 * 3000.0) / 180.0
        var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * x_pi)
        var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * x_pi)
        var bd_lon = z * Math.cos(theta) + 0.0065
        var bd_lat = z * Math.sin(theta) + 0.006
        var pt = new BMap.Point(bd_lon, bd_lat)
        return pt
      },
      toBMapPointArr(arr) {
        return arr.map((item) => {
          return this.toBMapPoint(...item)
        })
      },
      toAmapLnglat(bd_lng, bd_lat) {
        var X_PI = (Math.PI * 3000.0) / 180.0
        var x = bd_lng - 0.0065
        var y = bd_lat - 0.006
        var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI)
        var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI)
        var gg_lng = z * Math.cos(theta)
        var gg_lat = z * Math.sin(theta)
        return { lng: gg_lng, lat: gg_lat }
      },
      initMap() {
        if (this.map) {
          this.polyfillClearMap()
          return
        }
        console.log('MapLoad--load initMap')
        this.polyfillNewMap()
        // 添加控件
        this.addMapControl()
        // 初始化Map的回调
        this.initMapCallback()
      },
    },
  }
</script>

<style lang="less" scoped>
  .icon {
    margin-right: 6px;
  }
  .position-map {
    min-width: 600px;
    height: 600px;
    position: relative;

    .search {
      position: absolute;
      top: 20px;
      right: 100px;
      width: 260px;
      z-index: 1;
      background-color: #fff;
      padding: 6px;
    }

    .map {
      min-width: 600px;
      height: 600px;
    }
  }

  // 设计的弹框
  /* 2022-01-05最新设计：高785，宽1000 */
  .powerful-design-modal {
    .arco-modal {
      width: 1000px !important;
    }
  }
</style>
